#include "stdafx.h"
#include <math.h>
#include"omp.h"

#include "CeBrain.h"

CeBrain::CeBrain(void)
{
	memset( m_pNervusMap, 0, sizeof(m_pNervusMap) );
	m_pNervusValues = NULL;
	m_nNervusValuesCount = 0;
}


CeBrain::~CeBrain(void)
{
}

void CeBrain::ClearNervusMap( int nIdx )
{
	delete m_pNervusMap[nIdx];
	m_pNervusMap[nIdx] = NULL;
}

void CeBrain::BuildNervusMap( int nIdx,double tryValue )
{
	if( m_pNervusMap[nIdx]==NULL )
		m_pNervusMap[nIdx] = new CNervusMap();

	for( int i=0; i<NERVUS_MAP_WIDTH; i++ )
		for( int j=0; j<NERVUS_MAP_DEPTH; j++ )
		{
			NervusPOS pos = {i,j};
			m_pNervusMap[nIdx]->CreateNervusAtPos( pos );
		}

	for( int i=0; i<NERVUS_MAP_WIDTH; i++ )
		for( int j=0; j<NERVUS_MAP_DEPTH; j++ )
		{
			NervusPOS pos = {i,j};
			NervusPOS posTarget;
			for( int k=0; k<NERVUS_ANTENNA_NUM; k++ )
			{
				if( k==0 )
				{
					posTarget.nColumn = i;
					posTarget.nRow = j+1>=NERVUS_MAP_DEPTH ? 0 : j+1;
					if( j==NERVUS_MAP_DEPTH-1 )
						continue; //ignore for output pin.
				}
				else if( k== 1 )
				{
					posTarget.nColumn = i+1>=NERVUS_MAP_WIDTH ? 0 : i+1;
					posTarget.nRow = j+1>=NERVUS_MAP_DEPTH ? 0 : j+1;
				}
				else if( k== 2 )
				{
					posTarget.nColumn = i+1>=NERVUS_MAP_WIDTH ? 0 : i+1;
					posTarget.nRow = j;
				}
				
				//TRACE( "connect from {%d,%d}, %d, to {%d,%d}\n", pos.nColumn, pos.nRow, k, posTarget.nColumn, posTarget.nRow );
				m_pNervusMap[nIdx]->ConnectNervus( pos, k, posTarget );
			}
		}

	for( int j=0; j<m_nNervusValuesCount; j++ )
	{
		m_pNervusMap[nIdx]->GetNervus( m_pNervusValues[j].pos.nColumn, m_pNervusValues[j].pos.nRow )
			->SetValue(
			m_pNervusValues[j].value_real == 0 ? tryValue : m_pNervusValues[j].value_real/NV_DEVIDER,
			m_pNervusValues[j].value_image == 0 ? tryValue : m_pNervusValues[j].value_image/NV_DEVIDER );
	}
}

bool CeBrain::RunTrainingCase( int nIdx )
{
	CTrainingCase* pCase = m_pTrainingCaseDB->GetCase( nIdx );

	pCase->ConnectInputOutput( m_pNervusMap[nIdx] );
	pCase->InitOutSignal();

	for( int i=0; i<MAX_RUN_STEP; i++ )
	{
		pCase->TransmitSignal();

		m_pNervusMap[nIdx]->ProcessSignal();

		if( i>MAX_RUN_STEP-ALL_DIRECTION_COUNT )
		{
			pCase->GetOutputSignal();
		}
	}
	//TRACE("\n");

	bool bResult = pCase->CompareNervusOutputSignal( ) == RES_GOOD;
	//TRACE("[%d]result is %d;[%d %d %d %d] %d, %d\n",nIdx,bResult, m_nOutputSignal[0], m_nOutputSignal[1], m_nOutputSignal[2], m_nOutputSignal[3], (m_nOutputSignal[0] - m_nOutputSignal[2]), m_nOutputSignal[1] - m_nOutputSignal[3]);
	//TRACE("[%d]result is %d;[%lf %lf %lf] \n",nIdx,bResult, m_nOutputSignal[0].Model(), m_nOutputSignal[1].Model(), m_nOutputSignal[2].Model() );
	return bResult;
}

float CeBrain::RunAllTrainingCase( double tryValue )
{
	float fPassRate = 0;

	m_pTrainingCaseDB = new CTrainingCaseDB();
	m_pTrainingCaseDB->BuildAllCase();

	int nOkCount = 0;

	#pragma omp parallel for
	for( int i=0; i<MAX_CASE; i++ )
	{
		BuildNervusMap(i, tryValue);

		if( RunTrainingCase( i ) )
			nOkCount++;

		ClearNervusMap(i);
	}

	fPassRate = ((float)nOkCount)/MAX_CASE*100;
	TRACE( "Case Pass %d, when try %lf, pass rate: %f%%\n", nOkCount, tryValue, fPassRate );

	delete m_pTrainingCaseDB;
	return fPassRate;
}


